home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Game-Power
/
Amiga Game-Power.iso
/
power games ii
/
galactic worm
/
corewars
/
anleitung
/
kapiteliii
< prev
next >
Wrap
Text File
|
1994-05-20
|
17KB
|
375 lines
K a p i t e l 3 : T e c h n i k e n
_________________________________________
3.1 Strategien
______________
Es gibt grundsätzlich zwei verschiedene Haltungen, die ein Kampfprogramm
einnehmen kann: eine defensive und eine offensive. Wie immer ist die
Beschränkung auf nur eine dieser Strategien schlecht und fördert
uninteressante Kämpfe, deren Ausgehen oft unentschieden ist oder stark
vom Zufall der Positionierung der Programme im MARS-Speicher abhängt.
Ein Beispiel zur defensiven Haltung ist "Mice", das sich zwar sehr
schnell selbst kopiert und vermehrt, aber selten gewinnt. Die rein
offensive Haltung verkörpert "Gnom". Dieses Programm bombardiert den
gesamten MARS-Speicher im Abstand von fünf Zellen mit DAT 0 - Bomben.
"Gnom" selbst bleibt aber während des ganzen Kampfes an derselben Stelle
und kümmert sich nicht um die aktivitäten das gegnerischen Programmes.
Der typische Ablauf einer Schlacht zwischen diesen Beispielen "Mice" und
"Gnom" produziert ein Unentschieden, nachdem sich "Mice" bis auf 64
Tasks (das von MARS zugelassene Maximum) vermehrt hat und "Gnom"
vergebens versucht hat, die Abkömmlinge des Gegners zu löschen. Oft
ergeben sich auch Mutationen in Form von Knirpsen, wenn sich ein
"Mice"-Programm in das laufende "Gnom" hineinkopiert und wenn in diesem
Augenblick der Programmzeiger von "Gnom" auf die MOV-Anweisung des
"mice"-Fragmentes zurückspringt.
Die beiden Grundstrategien treten im Programm "Chang" vermischt auf,
wenn auch das Gleichgewicht stark in defensiver Richtung verschoben ist.
Während "Chang" an seinem Ende einen Wurm aus Knirpsen produziert, die
nach einigen hundert Zyklen bereits über 90 Prozent aller "Chang"-Tasks
belegen, versucht ein einziger Programmzeiger verzweifelt, alle 16
Zellen eine DAT 0 - Bombe zu legen. Wenn - was wegen seiner Länge sehr
wahrscheinlich ist - dieser aggressive Teil von "Chang" früher oder
später vom Gegner zerstört ist, bleibt nur noch ein Unentschieden: Der
endlose Knirps-Wurm ist kaum zu löschen.
Zusammenfassend lässt sich sagen, dass sich ein gutes Kampfprogramm zu
mehr oder weniger gleichen Teilen verteidigend und angreifend verhalten
soll. Ein Beispiel für ein solches Gleichgewicht ist "MausefalleII".
Es ist offensiv, weil es nach gegnerischen Tasks sucht, diese einfängt
und schliesslich zerstört. Es ist aber gleichzeitig defensiv, weil es
an seinem unteren Ende ein wirksames Knirpsgrab unterhält, das von
hinten anmarschierende Knirpse des Gegners manchmal (nicht immer!)
abfangen kann.
3.2 Weitere Beispielprogramme
_____________________________
3.2.1 Chang
-----------
trap MOV #0
maketrap JMP trap
ptr DAT 9
start SPL maketrap
SPL lnge
SUB #16, ptr
MOV #0, @ptr
JMP start
lnge SPL 2
JMP lnge
MOV 0, 1
"Chang" verhält sich sehr unfair: Es produziert an seinem Ende in einer
Knirpsfabrik eine fast unbesiegbare Schlange von Knirpsen, die im
Abstand von einer Zelle hinter sich herlaufen. Ganz nebenbei befindet
sich an seinem Beginn ein Knirpsgrab, das dort ankommende Kirpse
abfangen soll. Der mittlere Teil von "Chang" versucht, den Speicher im
Abstand von 16 Zellen zu bombardieren. Beim praktischen Experiment
zeigt sich, dass die Knirpsfabrik schon nach kurzer Zeit soviele
Programmzieger hervorgebracht hat, dass sich die Ausführung der anderen
Teile von "Chang" bis ins Nutzlose verlangsamt.
Trotzdem bietet "Chang" eine bemerkenswerte Technik: Die ersten beiden
Anweisungen starten das Knirpsgrab und die Knirpsfabrik. Auf diese
Weise kann ein Programm an mehreren Stellen gleichzeitig ausgeführt
werden. Je nach deren Wichtigkeit zum Ueberleben des Kampfprogrammes
können bestimmte Teile auch gleich von mehreren Zeigern hintereinander
bearbeitet werden. Denkbar wäre eine Verteilung von mehreren
Programmzeigern auf das Knirpsgrab, weil sonst ein einzelner Knirps
wegen seiner Geschwindigkeit zu leicht durch dessen Maschen schlüpfen
könnte.
"Chang" könnte stark verbessert werden, wenn an seinem Ende anstelle der
endlosen Knirpsschlange nur ein kurzer Wurm von vielleicht drei bis fünf
Knirpsen erzeugt würde. So hätten die DAT-Bomben einen grösseren
"Durchsatz", weil weniger Zeit durch unzählige Knirpse vergeudet würde.
3.2.2 Mice (Mäuse)
------------------
ptr DAT 0
start MOV #7, ptr
loop MOV @ptr, <5
DJN loop, ptr
SPL @3
ADD #653, 2
JMP start
DAT 833
Der phantasievolle Name dieses Programmes stammt von seiner ungehemmten
Vermehrungswut. "Mice" kopiert sich selber an eine 832 Zellen entfernte
Stelle im Speicher und hüpft anschliessend in diese Kopie, um sich
erneut zu vermehren. Das erste Programm seinerseits beginnt mit einer
neuen Kopie 1479 Zellen hinter der vorhergehenden - die Mäusefamilie ist
geboren.
Mit der ersten ausgeführten Zeile wird durch den MOV-Befehl ein Zähler
für die Anzahl der Zeilen, die kopiert werden sollen, initialisiert.
Nun wird in einer Schleife mit nur zwei Anweisungen das ganze Programm
kopiert. Der Befehl "MOV @ptr, <5" nimmt zuerst die Speicherzelle, die
durch den Zähler "ptr" bestimmt wird. Dann wird durch "<5" die
Anweisung "DAT 833" um eins vermindert. Die Zieladresse ergibt sich aus
dem neuen Ihnhalt der DAT-Anweisung: 832 Zeilen vom DAT-Befehl entfernt
liegt die gesuchte Zelle. Die durch "@ptr" gewonnene Programmzeile wird
nun auf diese Zieladresse kopiert. Der Befehl DJN sorgt dafür, dass
genau 7 Zeilen bewegt werden. Obwohl "Mice" eigentlich 8 Zeilen
umfasst, muss die erste DAT 0 - Anweisung nicht mitkopiert werden, weil
alle Speicherzellen vor einem Kampf gelöscht (mit DAT 0 gefüllt) werden.
Wenn alle Zeilen von "Mice" kopiert sind, wird mit dem SPL-Befehl das
neue Programm gestartet. Die Zeile mit der ADD-Anweisung dient zur
erhöhung der Position des nächsten Abkömmlings: 833 - 7 + 653 = 1479
Zellen hinter der Position des ursprünglichen Programmes. Der Letzte
Befehl von "Mice" beginnt den Zyklus erneut, indem wieder auf die erste
Anweisung gesprungen wird.
3.2.3 Mausefalle und MausefalleII
---------------------------------
num DAT 2660
falle SPL *
JMP falle
anzahl DAT 798
offset DAT 0
grube JMP -3
start SUB #10, offset
ADD #10, grube
MOV grube, @offset
DJN start, anzahl
end MOV #-4, anzahl
kill MOV #0, @anzahl
SUB #3, anzahl
DJN kill, num
MOV #0, falle
MOV #2660, num
JMP end
Das Programm besteht aus einer Falle und zwei Hauptschleifen,
gekennteichnet mit den Symbolen "start" und "kill". In der ersten
Schleife werden über den ganzen Speicher hinweg JMP-Befehle verteilt,
die alle auf die Falle weisen. Wenn einer der JMP-Befehle in ein
gegnerisches Programm einschlägt und früher oder später ausgeführt wird,
landet der betroffene Programmzeiger in der Falle: Ein SPL-Befehl, der
auf sich selber weist und der durch den unmittelbar darauf folgenden
Sprungbefehl immer wieder ausgeführt wird. Einmal in der Falle
gefangen, vermehrt sich dieser Programmzeiger immer wieder, bis
schlisslich kein einziges fremdes Programm mehr frei ist: Die Ausführung
der gegnerischen Programme kommt fast zum erliegen. Die Schwierigkeit
dieser Methode besteht in der Berechnung der Sprungweite der JMP-Bomben.
Durch den Befehl "ADD #10, grube" wird die Zahl 10 zum vorgegebenen
Sprungbefehl "JMP -3" addiert. Die Position der nächsten JMP-Bombe wird
durch "SUB #10, offset" bestimmt: Zehn Zellen hinter der zuletzt
gesetzten MP-Anweisung. Mit "MOV grube @offset" wird durch die
indirekte Adressierung der Inbhlt von "grube" (JMP) an die durch
"offset" bestimmte Speicherzelle kopiert - eine weitere Fallgrube ist
erstellt. Der Abschluss der Schleife bildet der DJN-Befehl, der den
ganzen Vorgang 1660 mal wiederholen lässt.
Die zweite Schleife ist etwas einfacher: Jede dritte Zelle des Speichers
wird mit Hilfe einer DAT 0 - Anweisung gelöscht. So sollte auch den
letzten verirrten gegnerischen Programmen der Garaus gemacht werden.
Wenn die Schleife beendet ist (nach 2660 Ausführungen) werden durch den
Befehl "MOV #0, falle" alle Programme, die sich in der Falle befinden,
mit einem Schlag gelöscht. Wenn jetzt noch kein Sieg erfolgt ist,
besteht immerhin noch die Gelegenheit eines Unentschiedens: Mit der
letzten JMP-Anweisung des Programmes wird die zweite Schleife nochmals
von Vorne begonnen.
Das Programm "MausefalleII" (es ist nicht hier abgedruckt, siehe
Programmdiskette im Verzeichnis 'Beispiele') besitzt an seinem Anfang
ein Knirpsgrab, wie es schon im ersten Kapitel vorgestellt wurde. Das
Grab wird durch die erste SPL-Anweisung nach dem Start aktiviert.
"Mausefalle" ist zwar ewas schneller als "MausefalleII", aber gegen
einen Knirps kann sie höchstens ein Unentschieden herausholen. Im
Gegensatz dazu gewinnt "MausefalleII" gegen "Mice" viel seltener, weil
die Bombardierungsgeschwindigkeit schon zu langsam ist.
Hier noch die Statistik einer Serie von 30 Zweikämpfen zwischen
"Mausefalle" und "Mice": 70% aller Kämpfe wurden von "Mausefalle"
gewonnen, 20% gingen auf das Konto von "Mice" und 10% der
Auseinandersetzungen verliefen unentschieden. Allerdings wurde für
diese Werte die Anzahl der Zyklen von 10000 (Standard) auf 20000 erhöht.
Vorsicht: "Mausefalle" ist mit nur 10000 Zyklen nicht lauffähig, weil
die zweite Schleife nicht zu Ende geführt werden kann. Dieser Mangel
lässt sich aber korrigieren, wenn die Schrittweite der JMP- und
DAT-Bomben etwas vermindert wird.
3.3 Die interne Darstellung eines Redcode Programmes
----------------------------------------------------
Das Entstehen eines Kampfprogrammes erstreckt sich über zwei Stufen: Das
Schreiben des Quelltextes mit dem Editor und das anschliessende
übersetzen dieses Textes durch den Assembler. Doch wie sieht eigentlich
das Programm nach der Assemblierung aus? Und wie wird das 8000 Zellen
umfassende MARS-Speicherfeld im Computer abgelegt? Diese beiden Fragen
sollen nun beantwortet werden. Vergessen Sie aber nicht, dass es für
das Schreiben eines Kampfprogrammes unwichtig ist, ob Sie über die
interne Verwaltung von MARS bescheid wissen oder nicht. Dieser letzte
Abschnitt ist vor Allem zur Information von Core Wars - Freaks gedacht,
die den Amiga auch selber programmieren. Wenn es Sie (noch) nicht
interessieren sollte, können Sie die Lektüre der Anleitung an dieser
Stelle beenden.
3.3.1 Redcode entschlüsselt
---------------------------
Die Ausgabe eines "richtigen" Assemblers besteht in Codes, die von der
CPU des dazugehörenden Computers als Befehle erkannt und ausgeführt
werden. Weil aber die Redcode-Anweisungen von keinem existierenden
Mikroprozessor verstanden werden können, muss eine imaginäre Redcode-CPU
softwaremässig simuliert werden, was auf dem Amiga durch das Core Wars -
Programm geschieht.
Der Assembler von MARS übersetzt jeden Redcode-Befehl und seine
Argumente in eine sieben Bytes lange Folge von einzelnen Daten. Eine
Folge von Daten, deren Anordnung einem im Voraus bestimmten Muster
entspricht, nennt man Datenstruktur. Diese Struktur, die jeweils eine
komplette Redcode-Anweisung enthält, ist in den einzelnen Bytes
folgendermassen aufgebaut:
Name Länge Bedeutung
_________________________________________________________________
Befehl 1 Byte Zahlencode des Redcode-Befehls. Der Wert
kann 0 bis 8 oder 10 sein, je nach Anweisung
(Tabelle am Ende dieses Kapitels).
Modus A 1 Byte Adressierungsart des ersten Argumentes,
kann einen Wert von 0 bis 3 für unmittelbar,
direkt, indirekt und indirekt-inkrement annehmen.
Wert A 2 Bytes Der reine Zahlenwert des ersten Argumentes. Er
muss immer zwischen -7999 und 7999 liegen.
Modus B 1 Byte Adressierungsart des zweiten Argumentes.
Wert B 2 Bytes Zahlenwert des zweiten Argumentes.
_________________________________________________________________
Total 7 Bytes
=================
Ein Programm, das vom Assembler übersetzt wurde, besteht also nicht mehr
aus lesbarem Text, sondern aus einer Folge von solchen Datenstrukturen.
Die Argumente eines Befehles setzen sich aus je einem Modus/Wert Paar
zusammen. Modus A und Wert A ergeben somit im Verein das Argument A,
für Argument B gilt dasselbe in grün.
Die Werte A und B dürfen Zahlen von -7999 bis +7999 beinhalten.
Eigentlich ist dies schon doppelt soviel als nötig ist, weil der
MARS-Speicher nur 8000 Zellen (0 bis 7999) umfasst. Der Grund dafür ist
die Lesbarkeit eines schon assemblierten Programmes:
Ein Sprung um 7992 Adressen nach vorne wird verständlicher, wenn man
negative Zahlen für Rückwärtssprünge verwendet. Der Befehl lautet dann:
Springe um 8 Adressen zurück.
3.3.2 MARS-Speicher im Amiga
----------------------------
Vielleicht haben Sie nun schon eine Vorahnung, wie das MARS-Speicherfeld
im Computer angelegt ist: Die 8000 Adressen von MARS bestehen aus einer
Liste mit 8000 der oben beschriebenen Befehlsstrukturen. Beim Starten
eines Spiels werden zuerst alle Elemente der Liste gelöscht (es wird mit
anderen Worten in jede der Strukturen eine DAT 0 - Anweisung
geschrieben) und die beiden Kampfprogramme werden an zufälligen
Startplätzen eingelesen. Der Zugriff auf die einzelnen Zellen erfolgt
durch ihre Nummern: Jede Zahl, die eine Adresse im Speicherfeld
darstellt, wird mit Hilfe einer Modulo-Operation (Division mit
Ermittlung des Restes) wenn nötig auf einen Wert zwischen 0 und 7999
inklusive verkleinert. Das Ergebnis ist dann die Nummer der
betreffenden Speicherzelle.
3.3.3 Grenzen dieser Darstellung
--------------------------------
Wir haben die Grösse von 7 Bytes einer Redcode-Anweisung deshalb
gewählt, weil sie uns als guter Kompromiss zwischen Länge,
Geschwindigkeit und Erweiterbarkeit erscheint. Die Möglichkeit der
Erweiterung wird klarer, wenn Sie sich die theoretisch darstellbaren
Werte von Befehl, Modus und Wert vor Augen führen:
Befehl = 1 Byte = 8 Bit = 2 hoch 8 = 256 verschiedene Zustände
Modus = 1 Byte = 8 Bit = 2 hoch 8 = 256 verschiedene Zustände
Wert = 2 Byte = 16 Bit = 2 hoch 16 = 65536 verschiedene Zustände
Demnach könnten noch 246 weitere Redcode-Befehle und 252 neue
Adressierungsarten eingeführt und das MARS-Speicherfeld um 57536 Zellen
erweitert werden. Die Geschwindigkeit war das wichtigste Kriterium: Der
Prozessor des Amiga besitzt Befehle, die unter anderem auch mit 16-Bit
Werten sehr schnell hantieren können. Der reine Informationsgehalt
einer Redcode-Anweisung liesse sich in insgesamt 34 Bits darstellen. Um
jedoch diese Bits bei jedem Zugriff auf einen Befehl und seine Argumente
auseinanderzupflücken, ginge viel zuviel Zeit verloren - ein Kampf
zwischen zwei Programmen würde sich unnötig in die Länge ziehen.
Kommen wir zum dritten Punkt, der Länge einer MARS- Speicherzelle. Der
insgesamt von MARS benötigte Speicherplatz im RAM des Computers beträgt
im besten Falle 8000 mal 7, also 56000 Bytes (= 56 KBytes). Wenn wir
dieselbe Rechnung mit der vorhin erwähnten 34-Bit Notation durchführen,
kommen wir auf einen Verbrauch von 34000 Bytes. Auf einem Computer mit
512 KByte RAM in der Grundausstattung erschien es uns vorteilhafter,
zugunsten der Kampfgeschwindigkeit auf die vergebenen 20 KByte zu ver-
zichten.
3.3.4 Tabelle der Befehlscodes
------------------------------
Hier folgt eine Tabelle aller Redcode-Befehle mit den dazugehörenden
Befehlscodes und den erlaubten Adressierungmodi. Die Zeichen, die nach
den Kennbuchstaben A und B stehen, stellen die erlaubten
Adressierungsarten dar. Wenn Sie sich ein bereits assembliertes
Programm anschauen, können Sie die dort auftretenden Codes mit Hilfe der
Tabelle entschlüsseln. Anstelle der Zeichen #, $, @ und < stehen im
lauffähigen Programm die Zahlen 0, 1, 2 und 3.
Befehl Arg. A Arg. B Code Bedeutung
_________________________________________________________________
DAT - B: $ 0 Daten
MOV A: #$@< B: $@< 1 Uebertragen
ADD A: #$@< B: $@< 2 Addieren
SUB A: #$@< B: $@< 3 Subtrahieren
JMP A: $@< - 4 Springen
JMZ A: $@< B: #$@< 5 Springen, wenn Null
JMN A: $@< B: #$@< 6 Springen, wenn nicht Null
DJN A: $@< B: #$@< 7 Vermindern und Springen
CMP A: #$@< B: #$@< 8 Vergleiche
SPL - B: $@< 10 Spalte auf
3.3.4 Das War's
---------------
Sie haben sich hiermit bis zum Ende der Anleitung durchgeackert und
können nun mit Recht von sich behaupten, ein Redcode Programmierer zu
sein. Wir hoffen, dass es Ihnen Spass gemacht hat und es noch machen
wird, sich mit diesem neuen Spielprinzip auseinanderzusetzen.
Der Rest der Anleitung besteht aus den zwei Anhängen, die verschiedene
Informationen zu Core Wars, ein Stichwortverzeichnis und ein kleines
Begriffsverzeichnis enthalten.